/* 
自定义Promise
*/
((window) => {
    // 定义状态值常量
    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
  
    /**
     * 构造函数
     * @param  excutor 执行器函数
     */
  
    /* 
      promise对象内部要存储哪些信息?
        1. 状态: pending/fulfilled/rejected  ==> state
        2. 结果数据: undefined/value/reason  ==> data
        3. 保存待处理回调的数组: [{resolved () {}, rejected () {}}, {resolved () {}, rejected () {}}] => callbacks
     
        在构造函数中, 会立即同步调用执行器函数, 并传入resolve和reject 两个函数
  
        resolve函数
          参数: value
          作用: 将promise的状态改为resolved, 将value保存到data, 异步调用所有成功的回调
        reject函数
          参数: reason
          作用: 将promise的状态改为rejected, 将reason保存到data, 异步调用所有失败的回调
      */
    function Promise(excutor) {
      /* 初始化3个属性 */
      // 1. 状态: pending/fulfilled/rejected  ==> state
      this.state = PENDING;
      // 2. 结果数据: undefined/value/reason  ==> data
      this.data = undefined;
      // 3. 保存待处理回调的数组: [{resolved () {}, rejected () {}}, {resolved () {}, rejected () {}}] => callbacks
      this.callbacks = [];
  
      const self = this;
  
      /* 
      resolve函数
          参数: value
          作用: 将promise的状态改为resolved, 将value保存到data, 异步调用所有成功的回调
      */
      function resolve(value) {
        // 只有当前状态为pendding, 才向下处理
        if (self.state!==PENDING) return
  
        // 改状态为成功的
        self.state = FULFILLED
        // 保存数据
        self.data = value
        // 异步执行callbacks中所有成功的回调
        // 我们没办法直接向微队列中添加回调 => 只能用宏队列了 setTimeout
        setTimeout(() => {
          self.callbacks.forEach(callbackObj => callbackObj.resolved(value))
        }, 0)
        
      }
  
      /* 
      reject函数
          参数: reason
          作用: 将promise的状态改为rejected, 将reason保存到data, 异步调用所有失败的回调
      */
      function reject(reason) {
        // 只有当前状态为pendding, 才向下处理
        if (self.state!==PENDING) return
        
        // 改状态为失败的
        self.state = REJECTED
        // 保存数据
        self.data = reason
        // 异步执行callbacks中所有成功的回调
        // 我们没办法直接向微队列中添加回调 => 只能用宏队列了 setTimeout
        setTimeout(() => {
          self.callbacks.forEach(callbackObj => callbackObj.rejected(reason))
        }, 0)
      }
  
      // 捕获执行器抛出的错误
      try {
        /*  在构造函数中, 会立即同步调用执行器函数, 并传入resolve和reject 两个函数 */
        excutor(resolve, reject);
      } catch (error) {
        // 将当前promise变为rejected, reason为error
        reject(error)
      }
      
    }
  
    /**
     * 指定成功和失败的回调, 并返回一个新的promise
     * @param {*} onResolved 成功的回调 => 用于得到成功的value
     * @param {*} onRejected 失败的回调 => 用于得到失败的reason
     */
    Promise.prototype.then = function (onResolved, onRejected) {
      const self = this
  
      if (self.state===FULFILLED) { // 如果当前promise是成功的, 异步执行成功的回调
        setTimeout(() => {
          onResolved(self.data)
        }, 0)
      } else if (self.state===REJECTED) { // 如果当前promise是失败的, 异步执行失败的回调
        setTimeout(() => {
          onRejected(self.data)
        }, 0)
      } else { // 如果当前promise是pending, 保存成功和失败的回调
        this.callbacks.push({
          resolved: onResolved,
          rejected: onRejected
        })
      }
    };
  
    /**
     * 指定失败的回调, 并返回一个新的promise
     * @param {*} onRejected 失败的回调 => 用于得到失败的reason
     */
    Promise.prototype.catch = function (onRejected) {};
  
    /**
     *  返回一个成功的promise, value为指定的value
     * @param {*} value
     */
    Promise.resolve = function (value) {};
  
    /**
     *  返回一个失败的promise, reason为指定的reason
     * @param {*} reason
     */
    Promise.reject = function (reason) {};
  
    /**
     * 返回一个promise, 如果promises都成功, 它才成功, 成功的value为所有value组成的数组, 只要有一个失败, 那它就失败了
     * @param {*} promises
     */
    Promise.all = function (promises) {};
  
    /**
     * 返回一个promise, 由第一个完成的promie来决定它的结果
     * @param {*} promises
     */
    Promise.race = function (promises) {};
  
    /**
     * 返回一个promise, 当所有promise都完成时它就成功, value值为所有promise的value或reason组成的数组
     * @param {*} promises
     */
    Promise.allSettled = function (promises) {};
  
    window.Promise = Promise;
  })(window);
  